import React, { createContext, useContext, useEffect, useState, useMemo } from 'react'
import { bindActionCreators } from 'redux'

// 创建一个上下文对象，目的是为了在 Provider 组件中提供上下文store
const ThemeContext = createContext()

export function Provider(props) {
  const { store, children } = props

  return <ThemeContext.Provider value={{ store }}>
    {children}
  </ThemeContext.Provider>
}

export function connect(mapStateToProps, mapDispatchToProps) {
  mapStateToProps = mapStateToProps || ((state) => ({}));
  mapDispatchToProps = mapDispatchToProps || ((dispatch) => { })
  return function currying(Component) {
    // 柯里化函数接收一个组件后，再返回一个组件 
    // 实际上，这个返回的组件才是真正要使用的组件
    return function HOC(props) {
      const { store } = useContext(ThemeContext)
      const { getState, dispatch, subscribe } = store

      let [_, forceUpdate] = useState(0)

      useEffect(() => {
        let unsubscribe = subscribe(() => {
          console.log('>>>')
          // 保证只要事件池中的方法执行，这个组件就要更新
          forceUpdate(+new Date())
        })
        // 组件销毁上一帧时执行的回调
        return () => unsubscribe()
      }, [])

      let state = getState(),
        nextState = useMemo(() => {
          return mapStateToProps(state)
        }, [state]);

      let mapDispatch = {}

      if (typeof mapDispatchToProps === 'function') {
        mapDispatch = mapDispatchToProps(dispatch)
      } else {
        mapDispatch = bindActionCreators(mapDispatchToProps, dispatch)
      }
      return <Component {...props} {...nextState} {...mapDispatch}></Component>
    }
  }
}

